package ClientCommands;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import org.json.simple.JSONObject;

import Annotations.IsClientCommand;
import Commands.ClientCommandBase;
import Commands.ExecuteMethod;
import DomainLayer.AbstractEntity;
import DomainLayer.BaseMovieEntity;
import DomainLayer.MPAARatingStatus;
import DomainLayer.ProfitValueObject;
import Helpers.ApplicationLogger;
import Presenters.JSONPresenter;
import ServiceLayer.ServiceFacade;

@IsClientCommand
public class GetFirstTenMovies extends ClientCommandBase<JSONPresenter> {
	class MovieJSONPresenter implements JSONPresenter {
		public MovieJSONPresenter(BaseMovieEntity movie) {
			setActors(movie.getActors());
			setCover(movie.getCover());
			setGenre(movie.getGenre());
			setMovieDescription(movie.getMovieDescription());
			setName(movie.getName());
			setProfit(movie.getProfit());
			setRating(movie.getRating());
			setRatingIMDB(movie.getRatingIMDB());
			setRatingMPAA(movie.getRatingMPAA());
			// setId(movie.getId());
		}

		private String movieDescription;
		private double ratingIMDB;
		private MPAARatingStatus ratingMPAA;
		private int rating;
		private String name;

		private HashSet<String> genre;
		private String cover;

		private ProfitValueObject profit;
		private ArrayList<String> actors;

		// private Integer id;

		public ArrayList<String> getActors() {
			return actors;
		}

		public void setActors(ArrayList<String> actors) {
			this.actors = actors;
		}

		public String getCover() {
			return cover;
		}

		public void setCover(String cover) {
			this.cover = cover;
		}

		public MPAARatingStatus getRatingMPAA() {
			return ratingMPAA;
		}

		public void setRatingMPAA(MPAARatingStatus ratingMPAA) {
			this.ratingMPAA = ratingMPAA;
		}

		public HashSet<String> getGenre() {
			return genre;
		}

		public void setGenre(HashSet<String> genre) {
			this.genre = genre;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public String getMovieDescription() {
			return movieDescription;
		}

		public void setMovieDescription(String movieDescription) {
			this.movieDescription = movieDescription;
		}

		public double getRatingIMDB() {
			return ratingIMDB;
		}

		public void setRatingIMDB(double ratingIMDB) {
			this.ratingIMDB = ratingIMDB;
		}

		public int getRating() {
			return rating;
		}

		public void setRating(int rating) {
			this.rating = rating;
		}

		public ProfitValueObject getProfit() {
			return profit;
		}

		public void setProfit(ProfitValueObject profit) {
			this.profit = profit;
		}

		// public Integer getId() {
		// return id;
		// }
		//
		// public void setId(Integer id) {
		// this.id = id;
		// }

		public String toJSONString() {
			StringBuffer sb = new StringBuffer();
			sb.append("{");
			// sb.append("\"" + JSONObject.escape("Id") + "\"");
			// sb.append(":");
			// sb.append("\"" + JSONObject.escape(getId().toString()) + "\"");
			// sb.append(",");
			sb.append("\"" + JSONObject.escape("MovieDescription") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getMovieDescription()) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("RatingIMDB") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRatingIMDB()))
					+ "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("RatingMPAA") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRatingMPAA()))
					+ "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Rating") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(String.valueOf(getRating()))
					+ "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Name") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getName()) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Genre") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(CollectionToString(getGenre()))
					+ "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Cover") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(getCover()) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitInRussia") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitInRussia())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitInUSA") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitInUSA())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitInEurope") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitInEurope())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitInOtherCountries") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitInOtherCountries())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitFromTV") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitFromTV())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("ProfitFromDVD") + "\"");
			sb.append(":");
			sb.append("\""
					+ JSONObject.escape(String.valueOf(getProfit()
							.getProfitFromDVD())) + "\"");
			sb.append(",");
			sb.append("\"" + JSONObject.escape("Actors") + "\"");
			sb.append(":");
			sb.append("\"" + JSONObject.escape(CollectionToString(getActors()))
					+ "\"");
			sb.append("}");
			return sb.toString();
		}
	}

	private String CollectionToString(Collection<String> collection) {
		String result = "";
		for (String s : collection) {
			result += s + ", ";
		}
		if ((result.length() > 2)
				&& (result.substring(result.length() - 2, result.length())
						.equals(", "))) {
			result = result.substring(0, result.length() - 2);
		}
		return result;
	}

	class MovieCollectionJSONPresenter implements JSONPresenter {

		MovieCollectionJSONPresenter(
				Collection<MovieJSONPresenter> moviesCollection) {
			this.moviesCollection = moviesCollection;
		}

		private Collection<MovieJSONPresenter> moviesCollection;

		@Override
		public String toJSONString() {
			ApplicationLogger.getInstance().LOG
					.info("Trying to make JSON string for movies collection... ("
							+ getCommandName() + ")");
			StringBuffer sb = new StringBuffer();
			sb.append("[");
			for (JSONPresenter jsonp : moviesCollection) {
				sb.append(jsonp.toJSONString() + ", ");
			}
			if ((sb.length() > 2)
					&& (sb.substring(sb.length() - 2, sb.length()).equals(", "))) {
				sb.delete(sb.length() - 2, sb.length());
			}
			sb.append("]");
			ApplicationLogger.getInstance().LOG
					.info("JSONString has been created: " + sb);
			return sb.toString();
		}

	}

	public GetFirstTenMovies() {
		setCommandName("GetFirstTenMovies");
		setCommandDescription("Get first ten movies");
		setExecuteMethod(ExecuteMethod.ServerOnly);
	}

	@Override
	protected void ExecuteInternal() throws IOException {
		Collection<MovieJSONPresenter> movieList = new ArrayList<MovieJSONPresenter>();
		MovieCollectionJSONPresenter result = null;
		try {
			ServiceLayer.ServiceFacade sf = new ServiceFacade();
			Collection<AbstractEntity> movies = (Collection<AbstractEntity>) sf
					.GetFirstTenMovies();
			for (AbstractEntity movieEntity : movies) {
				movieList.add(new MovieJSONPresenter(
						(BaseMovieEntity) movieEntity));
			}
			ApplicationLogger.getInstance().LOG
					.info("Request from DB comleted! (" + getCommandName()
							+ ")");
			result = new MovieCollectionJSONPresenter(movieList);
		} catch (Throwable e) {
			ApplicationLogger.getInstance().LOG.error(e.getMessage());
		}
		if (movieList.isEmpty()) {
			setIsNull(true);
		}
		ApplicationLogger.getInstance().LOG.info("Trying to ser tesult... ("
				+ getCommandName() + ")");
		setResult(result);
		ApplicationLogger.getInstance().LOG
				.info("Execute internal completed! (" + getCommandName() + ")");
	}

	public void FillFromJSON(JSONObject jObj) {
		super.FillFromJSON(jObj);
	}

	public String toJSONString() {
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("\"" + JSONObject.escape("CommandName") + "\"");
		sb.append(":");
		sb.append("\"" + JSONObject.escape(getCommandName()) + "\"");
		sb.append(",");
		sb.append("\"" + JSONObject.escape("CommandDescription") + "\"");
		sb.append(":");
		sb.append("\"" + getCommandDescription() + "\"");
		sb.append(",");
		sb.append("\"" + JSONObject.escape("ExecuteMethod") + "\"");
		sb.append(":");
		sb.append("\"" + getExecuteMethod() + "\"");
		sb.append("}");
		return sb.toString();
	}
}
